package com.example.springbootusecase.service;

import com.example.springbootusecase.bo.Product;
import com.example.springbootusecase.bo.ProductEs;
import com.example.springbootusecase.mapper.ProductEsRepository;
import com.example.springbootusecase.mapper.ProductJpaRepository;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ProductService {
    @Lazy
    @Autowired
    private ProductService selfProxy;

    @Autowired
    private ProductEsRepository productEsRepository;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private ProductJpaRepository productJpaRepository;  // 操作 MySQL

    @Autowired
    private RestHighLevelClient client;


    // 从 MySQL 批量同步到 Elasticsearch
    @Transactional(rollbackFor = Exception.class)
    public void syncAllProductsToES() {
        List<Product> products = productJpaRepository.findAll();
        // 转换 Product → ProductEs
        List<ProductEs> esProducts = products.stream().map(product -> {
            ProductEs es = new ProductEs();
            BeanUtils.copyProperties(product, es);
            return es;
        }).collect(Collectors.toList());

        productEsRepository.saveAll(esProducts);  // 批量写入 Elasticsearch
        System.out.println("✅ 数据同步完成：" + esProducts.size() + " 条数据已写入 Elasticsearch");
    }

    // 添加或更新数据
    public ProductEs save(ProductEs productEs) {
        return productEsRepository.save(productEs);
    }

    // ✅ 根据 ID 查询，排除逻辑删除
    public Optional<ProductEs> findById(Integer id) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("id", id))
                        .must(QueryBuilders.termQuery("isDeleted", "0")) // 过滤逻辑删除
                )
                .build();

        SearchHits<ProductEs> searchHits = elasticsearchRestTemplate.search(query, ProductEs.class);
        return searchHits.getSearchHits().stream()
                .map(SearchHit::getContent)
                .findFirst();
    }

    // ✅ 根据 name 查询，排除逻辑删除
    public ProductEs findByName(String name) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("name", name))
                        .must(QueryBuilders.termQuery("isDeleted", "0")) // 过滤逻辑删除
                )
                .build();

        SearchHits<ProductEs> searchHits = elasticsearchRestTemplate.search(query, ProductEs.class);
        return searchHits.getSearchHits().stream()
                .map(SearchHit::getContent)
                .findFirst()
                .orElse(null);
    }

    // ✅ 关键字搜索，排除逻辑删除
    public SearchHits<ProductEs> search(String field, String keyword) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery(field, keyword))
                        .must(QueryBuilders.termQuery("isDeleted", "0")) // 过滤逻辑删除
                )
                .build();
        return elasticsearchRestTemplate.search(query, ProductEs.class);
    }

    // 删除
    public void deleteById(Integer id) {
        productEsRepository.deleteById(id);
    }

    public void fixMissingIsDeletedField() {
        int batchSize = 10000; // 每次更新 1000 条，防止内存溢出
        int from = 0;

        while (true) {
            // 1. 分批查询数据
            SearchResponse response;
            try {
                SearchRequest searchRequest = new SearchRequest("products");
                SearchSourceBuilder sourceBuilder = new SearchSourceBuilder()
                        .query(QueryBuilders.boolQuery()
                                .mustNot(QueryBuilders.existsQuery("isDeleted"))) // 找出没有 is_deleted 的数据
                        .from(from)
                        .size(batchSize);

                searchRequest.source(sourceBuilder);
                response = client.search(searchRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }

            if (response.getHits().getHits().length == 0) {
                break; // 没有更多数据了
            }

            // 2. 批量更新数据
            BulkRequest bulkRequest = new BulkRequest();
            for (org.elasticsearch.search.SearchHit hit : response.getHits().getHits()) {
                UpdateRequest updateRequest = new UpdateRequest("products", hit.getId())
                        .doc("isDeleted", "0"); // 给缺失字段的数据补上 is_deleted=0
                bulkRequest.add(updateRequest);
            }

            try {
                client.bulk(bulkRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }

            from += batchSize;
        }

        System.out.println("✅ 所有数据已更新，确保 is_deleted=0");
    }

}

